home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / ddx / Xsun / sunKbd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-11  |  15.0 KB  |  534 lines

  1. /*-
  2.  * sunKbd.c --
  3.  *    Functions for retrieving data from a keyboard.
  4.  *
  5.  * Copyright (c) 1987 by the Regents of the University of California
  6.  *
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  *
  15.  */
  16.  
  17. /************************************************************
  18. Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
  19.  
  20.                     All Rights Reserved
  21.  
  22. Permission  to  use,  copy,  modify,  and  distribute   this
  23. software  and  its documentation for any purpose and without
  24. fee is hereby granted, provided that the above copyright no-
  25. tice  appear  in all copies and that both that copyright no-
  26. tice and this permission notice appear in  supporting  docu-
  27. mentation,  and  that the names of Sun or MIT not be used in
  28. advertising or publicity pertaining to distribution  of  the
  29. software  without specific prior written permission. Sun and
  30. M.I.T. make no representations about the suitability of this
  31. software for any purpose. It is provided "as is" without any
  32. express or implied warranty.
  33.  
  34. SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
  35. INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
  36. NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
  37. ABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  38. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
  39. PROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
  40. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
  41. THE USE OR PERFORMANCE OF THIS SOFTWARE.
  42.  
  43. ********************************************************/
  44.  
  45. #ifndef    lint
  46. static char sccsid[] = "%W %G Copyright 1987 Sun Micro";
  47. #endif
  48.  
  49.  
  50. #define Time SpriteTime
  51. #include <fs.h>
  52. #undef Time
  53. #define NEED_EVENTS
  54. #include "sun.h"
  55. #include <bit.h>
  56. #include <errno.h>
  57. #include <fcntl.h>
  58. #include <sys/file.h>
  59. #include <sys/time.h>
  60. #include "keysym.h"
  61. #include "keymap.h"
  62.  
  63. #define AUTO_GENERATED    0x10000
  64. #define MIN_KEYCODE    8       /* Keycode below which we may not transmit */
  65. #define ALL_KEYS_UP    127    /* all keys are up now */
  66.  
  67. /*
  68.  * Auto-repeat stuff.
  69.  */
  70. static enum {
  71.     REPEAT_LONG,        /* Start repeat with long timeout */
  72.     REPEAT_SHORT,        /* Start repeat with short timeout */
  73.     REPEAT_TIMEOUT,        /* In the middle of a timeout */
  74.     REPEAT_PENDING,        /* Repeat should be taken next */
  75.     REPEAT_NONE              /* No repeat should happen */
  76. } repeatPhase = REPEAT_NONE;
  77. static Mouse_Event    repeatEvent;    /* Event that will be repeated */
  78. static struct timeval     repeatTimeout;    /* Timeout to use for repeating */
  79. static unsigned int    repeatDelta;    /* Timeout length (ms) */
  80. /* The following two are set in sunIo.c */
  81. unsigned int        repeatLong=300;    /* Ms delay to begin repeat */
  82. unsigned int        repeatShort=10;    /* Ms delay to begin repeat */
  83.  
  84. typedef struct {
  85.     int              trans;              /* Original translation form */
  86. } SunKbPrivRec, *SunKbPrivPtr;
  87.  
  88. extern void    ProcessInputEvents();
  89. extern void    miPointerPosition();
  90.  
  91. static void       sunBell();
  92. static void       sunKbdCtrl();
  93. static Mouse_Event *sunKbdGetEvents();
  94. static void       sunKbdProcessEvent();
  95. static void       sunKbdDoneEvents();
  96. static KeybdCtrl  sysKbCtrl;
  97.  
  98. static SunKbPrivRec    sunKbPriv;  
  99. static KbPrivRec      sysKbPriv = {
  100.     -1,                /* Type of keyboard */
  101.     -1,                /* Descriptor open to device */
  102.     sunKbdGetEvents,        /* Function to read events */
  103.     sunKbdProcessEvent,        /* Function to process an event */
  104.     sunKbdDoneEvents,        /* Function called when all events */
  105.                 /* have been handled. */
  106.     (pointer)&sunKbPriv,    /* Private to keyboard device */
  107.     0,                /* offset for device keycodes */
  108.     &sysKbCtrl,            /* Initial full duration = .25 sec. */
  109. };
  110.  
  111. /*-
  112.  *-----------------------------------------------------------------------
  113.  * sunKbdProc --
  114.  *    Handle the initialization, etc. of a keyboard.
  115.  *
  116.  * Results:
  117.  *    None.
  118.  *
  119.  * Side Effects:
  120.  *
  121.  * Note:
  122.  *    When using sunwindows, all input comes off a single fd, stored in the
  123.  *    global windowFd.  Therefore, only one device should be enabled and
  124.  *    disabled, even though the application still sees both mouse and
  125.  *    keyboard.  We have arbitrarily chosen to enable and disable windowFd
  126.  *    in the keyboard routine sunKbdProc rather than in sunMouseProc.
  127.  *
  128.  *-----------------------------------------------------------------------
  129.  */
  130. int
  131. sunKbdProc (pKeyboard, what)
  132.     DevicePtr      pKeyboard;    /* Keyboard to manipulate */
  133.     int              what;            /* What to do to it */
  134. {
  135.     KbPrivPtr      pPriv;
  136.     register int  kbdFd;
  137.  
  138.     switch (what) {
  139.     case DEVICE_INIT:
  140.         if (pKeyboard != LookupKeyboardDevice()) {
  141.         ErrorF ("Cannot open non-system keyboard");
  142.         return (!Success);
  143.         }
  144.         
  145.         /*
  146.          * First open and find the current state of the keyboard.
  147.          */
  148.         if (sysKbPriv.fd < 0) {
  149.             ReturnStatus status;
  150.  
  151.         status = Fs_Open("/dev/mouse",
  152.             FS_NON_BLOCKING|FS_READ|FS_WRITE, 0, &sysKbPriv.fd);
  153.             if (status != 0) {
  154.             errno = Compat_MapCode(status);
  155.             Error ("Opening /dev/mouse");
  156.             return (!Success);
  157.         }
  158.         }
  159.  
  160.         /*
  161.          * Perform final initialization of the system private keyboard
  162.          * structure and fill in various slots in the device record
  163.          * itself which couldn't be filled in before.
  164.          */
  165.         pKeyboard->devicePrivate = (pointer)&sysKbPriv;
  166.         pKeyboard->on = FALSE;
  167.         sysKbCtrl = defaultKeyboardControl;
  168.         sysKbPriv.ctrl = &sysKbCtrl;
  169.  
  170.         /*
  171.          * ensure that the keycodes on the wire are >= MIN_KEYCODE
  172.          */
  173.          if (sunMapDesc.minKeyCode < MIN_KEYCODE) {
  174.          int    offset;
  175.  
  176.          offset = MIN_KEYCODE - sunMapDesc.minKeyCode;
  177.          sunMapDesc.minKeyCode += offset;
  178.          sunMapDesc.maxKeyCode += offset;
  179.          sysKbPriv.offset = offset;
  180.          }
  181.         InitKeyboardDeviceStruct(pKeyboard, &sunMapDesc, sunModMap,
  182.                      sunBell, sunKbdCtrl);
  183.         break;
  184.  
  185.     case DEVICE_ON:
  186.         pPriv = (KbPrivPtr)pKeyboard->devicePrivate;
  187.         kbdFd = pPriv->fd;
  188.         AddEnabledDevice(kbdFd);
  189.         pKeyboard->on = TRUE;
  190.         repeatPhase = REPEAT_NONE;
  191.         break;
  192.  
  193.     case DEVICE_CLOSE:
  194.     case DEVICE_OFF:
  195.         pPriv = (KbPrivPtr)pKeyboard->devicePrivate;
  196.         kbdFd = pPriv->fd;
  197.         RemoveEnabledDevice(kbdFd);
  198.         pKeyboard->on = FALSE;
  199.         repeatPhase = REPEAT_NONE;
  200.         break;
  201.     }
  202.     return (Success);
  203. }
  204.  
  205. /*-
  206.  *-----------------------------------------------------------------------
  207.  * sunBell --
  208.  *    Ring the terminal/keyboard bell
  209.  *
  210.  * Results:
  211.  *    Ring the keyboard bell for an amount of time proportional to
  212.  *    "loudness."
  213.  *
  214.  * Side Effects:
  215.  *    None, really...
  216.  *
  217.  *-----------------------------------------------------------------------
  218.  */
  219. static void
  220. sunBell (loudness, pKeyboard)
  221.     int              loudness;        /* Percentage of full volume */
  222.     DevicePtr      pKeyboard;        /* Keyboard to ring */
  223. {
  224.     KbPrivPtr        pPriv = (KbPrivPtr)pKeyboard->devicePrivate;
  225.     char        kbdCmd;
  226.     struct timeval    sleepTime;
  227.  
  228.     if (loudness == 0) {
  229.     return;
  230.     }
  231.  
  232.     kbdCmd = KBD_BELL_ON;
  233.     (void) write(pPriv->fd, &kbdCmd, 1);
  234.  
  235.     sleepTime.tv_usec = pPriv->ctrl->bell_duration * 1000;
  236.     sleepTime.tv_sec = 0;
  237.     while (sleepTime.tv_usec >= 1000000) {
  238.     sleepTime.tv_sec += 1;
  239.     sleepTime.tv_usec -= 1000000;
  240.     }
  241.     (void) select(0, (int *) 0, (int *) 0, (int *) 0, &sleepTime);
  242.  
  243.     kbdCmd = KBD_BELL_OFF;
  244.     (void) write(pPriv->fd, &kbdCmd, 1);
  245. }
  246.  
  247. /*-
  248.  *-----------------------------------------------------------------------
  249.  * sunKbdCtrl --
  250.  *    Alter some of the keyboard control parameters
  251.  *
  252.  * Results:
  253.  *    None.
  254.  *
  255.  * Side Effects:
  256.  *    Some...
  257.  *
  258.  *-----------------------------------------------------------------------
  259.  */
  260. static void
  261. sunKbdCtrl (pKeyboard, ctrl)
  262.     DevicePtr      pKeyboard;        /* Keyboard to alter */
  263.     KeybdCtrl     *ctrl;
  264. {
  265.     KbPrivPtr      pPriv;
  266.     char      kbCmd;
  267.  
  268.     pPriv = (KbPrivPtr)pKeyboard->devicePrivate;
  269.  
  270.     pPriv->ctrl = ctrl;
  271.     if (ctrl->click) {
  272.     kbCmd = KBD_CLICK_ON;
  273.     } else {
  274.     kbCmd = KBD_CLICK_OFF;
  275.     }
  276.  
  277.     (void) write(pPriv->fd, &kbCmd, 1);
  278.  
  279.     if (!ctrl->autoRepeat) {
  280.     repeatPhase = REPEAT_NONE;
  281.     }
  282. }
  283.  
  284. /*-
  285.  *-----------------------------------------------------------------------
  286.  * sunKbdGetEvents --
  287.  *    Return the events waiting in the wings for the given keyboard.
  288.  *
  289.  * Results:
  290.  *    A pointer to an array of Firm_events or (Firm_event *)0 if no events
  291.  *    The number of events contained in the array.
  292.  *    A boolean as to whether more events might be available.
  293.  *    If there are no keyboard events ready and autoRepeatKeyDown > 0,
  294.  *    then *pNumEvents is set to 1 and Firm_event id is set to
  295.  *    AUTOREPEAT_EVENTID.  In sunKbdProcessEvent, if autoRepeatKeyDown > 0
  296.  *    and Firm_event id == AUTOREPEAT_EVENTID, then the event buffer is
  297.  *    ignored and the    event is generated from the last KeyPress event.
  298.  *
  299.  * Side Effects:
  300.  *    None.
  301.  *-----------------------------------------------------------------------
  302.  */
  303. static Mouse_Event *
  304. sunKbdGetEvents (pKeyboard, pNumEvents)
  305.     DevicePtr      pKeyboard;        /* Keyboard to read */
  306.     int              *pNumEvents;        /* Place to return number of events */
  307. {
  308.     int              nBytes;        /* number of bytes of events available. */
  309.     KbPrivPtr      pPriv;
  310.     static Mouse_Event    evBuf[MAXEVENTS];   /* Buffer for Firm_events */
  311.  
  312.     if (repeatPhase == REPEAT_PENDING) {
  313.     /*
  314.      * This will only have been set if no streams were really ready, thus
  315.      * there are no events to read from /dev/mouse.
  316.      */
  317.     repeatEvent.flags |= KEY_UP;
  318.     repeatEvent.time += repeatDelta / 2;
  319.     evBuf[0] = repeatEvent;
  320.  
  321.     repeatEvent.flags &= ~KEY_UP;
  322.     repeatEvent.time += repeatDelta / 2;
  323.     evBuf[1] = repeatEvent;
  324.  
  325.     *pNumEvents = 2;
  326.  
  327.     repeatPhase = REPEAT_SHORT;
  328.     } else {
  329.         pPriv = (KbPrivPtr) pKeyboard->devicePrivate;
  330.         nBytes = read (pPriv->fd, evBuf, sizeof(evBuf));
  331.     
  332.         if (nBytes < 0) {
  333.         if (errno == EWOULDBLOCK) {
  334.             *pNumEvents = 0;
  335.         } else {
  336.             Error ("Reading keyboard");
  337.             FatalError ("Could not read the keyboard");
  338.             }
  339.         } else {
  340.         *pNumEvents = nBytes / sizeof (Mouse_Event);
  341.         }
  342.     }
  343.  
  344.     return (evBuf);
  345. }
  346.  
  347. /*-
  348.  *-----------------------------------------------------------------------
  349.  * sunKbdProcessEvent --
  350.  *
  351.  * Results:
  352.  *
  353.  * Side Effects:
  354.  *
  355.  * Caveat:
  356.  *      To reduce duplication of code and logic (and therefore bugs), the
  357.  *      sunwindows version of kbd processing (sunKbdProcessEventSunWin())
  358.  *      counterfeits a firm event and calls this routine.  This
  359.  *      couunterfeiting relies on the fact this this routine only looks at the
  360.  *      id, time, and value fields of the firm event which it is passed.  If
  361.  *      this ever changes, the sunKbdProcessEventSunWin will also have to
  362.  *      change.
  363.  *
  364.  *-----------------------------------------------------------------------
  365.  */
  366. static void
  367. sunKbdProcessEvent (pKeyboard, ev)
  368.     DevicePtr      pKeyboard;
  369.     Mouse_Event      *ev;
  370. {
  371.     xEvent        xE;
  372.     register KbPrivPtr    pPriv;
  373.     register int      smask;
  374.     PtrPrivPtr          ptrPriv;
  375.  
  376.     pPriv = (KbPrivPtr)pKeyboard->devicePrivate;
  377.     ptrPriv = (PtrPrivPtr) LookupPointerDevice()->devicePrivate;
  378.  
  379.     xE.u.keyButtonPointer.time = ev->time;
  380.     xE.u.u.detail = ev->key + pPriv->offset;
  381.     if (ev->key == ALL_KEYS_UP) {
  382.     xE.u.u.type = KeyRelease;
  383.     repeatPhase = REPEAT_NONE;
  384.     } else if (ev->flags & KEY_UP) {
  385.     xE.u.u.type = KeyRelease;
  386.     if (!(ev->flags & AUTO_GENERATED) &&
  387.          (repeatPhase != REPEAT_NONE) &&
  388.          (repeatEvent.key == ev->key)) {
  389.         /*
  390.          * Turn off repeat if we got a real up event for the key
  391.          * being repeated
  392.          */
  393.         repeatPhase = REPEAT_NONE;
  394.     }
  395.     } else {
  396.     xE.u.u.type = KeyPress;
  397.     if ((repeatPhase != REPEAT_SHORT) &&
  398.         (pPriv->ctrl->autoRepeat ||
  399.          Bit_IsSet (xE.u.u.detail, pPriv->ctrl->autoRepeats))) {
  400.          repeatEvent = *ev;
  401.          repeatEvent.flags |= AUTO_GENERATED;
  402.          repeatPhase = REPEAT_LONG;
  403.     }
  404.     }
  405.     miPointerPosition (screenInfo.screens[0],
  406.                &xE.u.keyButtonPointer.rootX,
  407.                &xE.u.keyButtonPointer.rootY);
  408.  
  409.     (* pKeyboard->processInputProc) (&xE, pKeyboard, 1);
  410. }
  411.  
  412. /*-
  413.  *-----------------------------------------------------------------------
  414.  * sunDoneEvents --
  415.  *    Nothing to do, here...
  416.  *
  417.  * Results:
  418.  *
  419.  * Side Effects:
  420.  *
  421.  *-----------------------------------------------------------------------
  422.  */
  423. /*ARGSUSED*/
  424. static void
  425. sunKbdDoneEvents (pKeyboard)
  426.     DevicePtr      pKeyboard;
  427. {
  428. }
  429.  
  430. /*-
  431.  *-----------------------------------------------------------------------
  432.  * LegalModifier --
  433.  *    See if a key is legal as a modifier. We're very lenient around,
  434.  *    here, so we always return true.
  435.  *
  436.  * Results:
  437.  *    TRUE.
  438.  *
  439.  * Side Effects:
  440.  *    None.
  441.  *
  442.  *-----------------------------------------------------------------------
  443.  */
  444. Bool
  445. LegalModifier(key)
  446. {
  447.     return (TRUE);
  448. }
  449.  
  450. static KeybdCtrl *pKbdCtrl = (KeybdCtrl *) 0;
  451.  
  452. /*-
  453.  *-----------------------------------------------------------------------
  454.  * sunBlockHandler --
  455.  *    Tell the OS layer when to timeout to implement auto-repeat.
  456.  *
  457.  * Results:
  458.  *    None.
  459.  *
  460.  * Side Effects:
  461.  *    The timeout value may be overwritten.
  462.  *
  463.  *-----------------------------------------------------------------------
  464.  */
  465. void
  466. sunBlockHandler (index, pKeyboard, ppTime, pReadMask)
  467.     int                index;        /* Screen index */
  468.     DevicePtr        pKeyboard;    /* Keyboard for which to do auto-repeat */
  469.     struct timeval  **ppTime;     /* Pointer to timeout to use */
  470.     int                *pReadMask;    /* Mask the OS Layer will use for select. */
  471. {
  472.     if (repeatPhase == REPEAT_LONG) {
  473.     /*
  474.      * Beginning long timeout
  475.      */
  476.     repeatDelta = repeatLong;
  477.     } else if (repeatPhase == REPEAT_SHORT) {
  478.     /*
  479.      * Beginning short timeout
  480.      */
  481.     repeatDelta = repeatShort;
  482.     } else if (repeatPhase == REPEAT_NONE) {
  483.     /*
  484.      * No repeat necessary -- it can block as long as it wants to
  485.      */
  486.     return;
  487.     } else if (repeatPhase == REPEAT_TIMEOUT) {
  488.     /*
  489.      * Interrupted timeout -- use old timeout (that was modified by
  490.      * select in the OS layer)
  491.      */
  492.     *ppTime = &repeatTimeout;
  493.     return;
  494.     }
  495.     repeatTimeout.tv_sec = repeatDelta / 1000;
  496.     repeatTimeout.tv_usec = repeatDelta * 1000;
  497.     repeatPhase = REPEAT_TIMEOUT;
  498.     *ppTime = &repeatTimeout;
  499. }
  500.  
  501. /*-
  502.  *-----------------------------------------------------------------------
  503.  * sunWakeupHandler --
  504.  *    Figure out if should do a repeat when the server wakes up. Because
  505.  *    select will modify repeatTimeout to contain the time left, we
  506.  *    can tell if the thing timed out.
  507.  *
  508.  * Results:
  509.  *    None.
  510.  *
  511.  * Side Effects:
  512.  *    repeatPhase may be changed to REPEAT_PENDING. If it is, *pNumReady
  513.  *    will be set to 1 and the keyboard's stream marked ready in the
  514.  *    result mask.
  515.  *
  516.  *-----------------------------------------------------------------------
  517.  */
  518. void
  519. sunWakeupHandler (index, pKeyboard, pNumReady, pReadMask)
  520.     int              index;        /* Screen index */
  521.     DevicePtr      pKeyboard;    /* Keyboard to repeat */
  522.     int              *pNumReady;     /* Pointer to number of ready streams */
  523.     int              *pReadMask;    /* Ready streams */
  524. {
  525.     KbPrivPtr      pPriv;
  526.  
  527.     pPriv = (KbPrivPtr)pKeyboard->devicePrivate;
  528.     
  529.     if ((repeatPhase == REPEAT_TIMEOUT) && (pNumReady == 0)) {
  530.     repeatPhase = REPEAT_PENDING;
  531.     ProcessInputEvents();
  532.     }
  533. }
  534.